using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace SanFS.Logging
{
	public class Log
	{
		[Flags()]
			public enum Layer
		{
			None		= 0x0000,
			Hardware	= 0x0001,
			Media		= 0x0002,
			Scheduler	= 0x0004,
			Cache   	= 0x0008,
			All			= (Hardware | Media | Scheduler | Cache)
		}

		[Flags()]
			public enum Type
		{
			None			= 0x0000,
			Trace			= 0x0001,
			Debug			= 0x0002,
			Informative		= 0x0004,
			Warning			= 0x0008,
			Error			= 0x0010,
			Critical		= 0x0020,
			All				= (Trace | Debug | Informative | Warning | Error | Critical)
		}

		private static Mutex		Lock = new Mutex();	
		private static StreamWriter	SW = null;
		private static Layer		Layers = Layer.All;
		private static Type			Types = Type.All;

		public static void OpenLog(string Filename, Layer LogLayers, Type LogTypes)
		{
			try
			{
				Layers = LogLayers;
				Types = LogTypes;
				if (File.Exists(Filename))
					File.Delete(Filename);
				SW = new StreamWriter(Filename, true);
				WriteLine(" Log file opened");
			}
			catch (Exception ex)
			{
				throw new Exception("Unable to open log", ex);
			}
		}

		public static void CloseLog()
		{
			if (SW != null)
			{
				WriteLine(" Closing log file");
				SW.Close();
				SW = null;
			}
		}

		public static void WriteLine(	Layer	Layer,
										Type	Type,
										string	Format, 
										params	object[] Parameters)
		{
			if (((Layers & Layer) == Layer) &&
				((Types & Type) == Type))
			{
				StackTrace	st = new StackTrace(1, true);
				StackFrame	f = st.GetFrame(0);
				string	Location = f.GetMethod().ReflectedType.Name + "." + f.GetMethod().Name;
				WriteLine("[{0}][{1}][{2}] {3}", Layer, Type, Location, String.Format(Format, Parameters));
			}
		}

		private static void WriteLine(string Format, params object[] Parameters)
		{
			WriteLine(String.Format(Format, Parameters));
		}

		private static void WriteLine(string Line)
		{
			string	msg = String.Format("[{0}]{1}", DateTime.Now.ToString("dd-MM-yy HH:mm:ss:ff"), Line);
			System.Diagnostics.Debug.WriteLine(msg);

			if (SW != null)
			{
				Lock.WaitOne();
				try
				{
					SW.WriteLine(msg);
				}
				finally
				{
					Lock.ReleaseMutex();
				}
				SW.Flush();
			}
		}
	}  // END CLASS
}  // END NAMESPACE
